<template>
  <el-dialog
    :title="title"
    :visible="dialogVisible"
    width="40%"
    @close="handleClose()"
    @open="openDialog()"
  >
    <!-- 表单组件  el-form   label-width设置label的宽度   -->
    <!-- 匿名插槽 -->
    <el-form ref="deptForm" :model="form" :rules="rules" label-width="120px">
      <el-form-item label="部门名称" prop="name">
        <el-input
          v-model="form.name"
          style="width: 80%"
          placeholder="1-50个字符"
        />
      </el-form-item>
      <el-form-item label="部门编码" prop="code">
        <el-input
          v-model="form.code"
          style="width: 80%"
          placeholder="1-50个字符"
        />
      </el-form-item>
      <el-form-item label="部门负责人" prop="manager">
        <el-select
          v-model="form.manager"
          style="width: 80%"
          placeholder="请选择"
        >
          <el-option
            v-for="item in options"
            :key="item.id"
            :label="item.username"
            :value="item.username"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="部门介绍" prop="introduce">
        <el-input
          v-model="form.introduce"
          style="width: 80%"
          placeholder="1-300个字符"
          type="textarea"
          :rows="3"
        />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="handleClose()">取 消</el-button>
        <el-button type="primary" @click="addDepartList()">确 定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script>
import { getDepartUserInfo } from '@/api/user'
import {
  addDepartMentApi,
  getDepartMentApi,
  editDepartMentApi
} from '@/api/department'
export default {
  props: {
    // eslint-disable-next-line vue/require-prop-types
    dialogVisible: {
      typeof: Boolean,
      default: false
    },
    oldDepartList: {
      type: Array,
      required: true
    },
    pdata: {
      type: Object,
      required: true
    },
    title: {
      type: String,
      required: true
    }
  },
  data() {
    // 自定义校验：同级部门中禁止出现重复部门
    // 那么首先要获得{父级部门的id}和{父级部门下面所有的子部门的名称}，然后和用户输入的名称和编码进行对比，如果相同就报错提醒用户换个名称，如果不相同就正常将新增的部门添加到{数据库}中。
    const checkNameRepeat = (rule, value, callback) => {
      // arr用来存放父级部门下面所有的子部门的名称
      let arr = []
      // 现在我们进行验证，如果form有id，那么现在就是编辑状态。
      if (this.form.id) {
        // 当然，在编辑状态下，我们可以选择是否对部门名称进行修改。
        // 如果我们不对部门名称进行修改，那么直接放行
        if (this.pdata.name === value) {
          callback()
          return
        } else {
          // 如果我们修改了部门名称，那么就要让它和它的兄弟部门进行比较，不能让它和它兄弟部门的名称一样
          // 首先将和它是同一个父亲的兄弟们都找到
          arr = this.oldDepartList.filter((item) => {
            return item.pid === this.pdata.pid
          })
        }
      } else {
        // 这是新增部门的状态
        arr = this.oldDepartList.filter((item) => {
          return item.pid === this.pdata.id
        })
      }
      // 然后让它和这些兄弟们进行对比
      const flag = arr.some((item) => item.name === value)
      flag ? callback(new Error('已经出现了同名的部门！')) : callback()
    }
    // 自定义校验，新增的部门编码不能和已经存在的部门编码相同
    const checkCodeRepeat = (rule, value, callback) => {
      // 什么时候我们对code不进行校验？
      // 当我们有id的时候也就是在编辑状态下，
      // 并且当我们新修改的code和原来的code一样的时候【也就是没修改code】我们不进行校验了直接放行。
      if (this.form.id && value === this.pdata.code) {
        callback()
        return
      }
      // 当我们修改完毕之后的code和原来的code不一样的时候，我们还需要对其进行验证，看看修改完毕的code和现有的所有部门code有没有重复的。
      // 当然这里也是新增部门的时候，要对新增的部门的code是不是和现有的所有部门的code重复。
      const flag = this.oldDepartList.some((item) => {
        return item.code === value
      })
      flag ? callback(new Error('该部门编码已经存在！')) : callback()
    }
    return {
      form: {
        name: '', // 部门名称
        code: '', // 部门编码
        manager: '', // 部门管理者
        introduce: '' // 部门介绍
      },
      // 定义校验规则
      rules: {
        name: [
          {
            required: true,
            message: '部门名称不能为空',
            trigger: ['blur', 'change']
          },
          {
            min: 1,
            max: 50,
            message: '部门名称要求1-50个字符',
            trigger: ['blur', 'change']
          },
          // 为什么前面的校验都是失去焦点和值改变，而到了我们自定义校验就只有一个失去焦点呢？
          // 因为我们的自定义校验里面既有遍历又有比较，如果值一改变就触发自定义校验，那就平白无故浪费了大量的资源，所以只有一个失去焦点就行
          { validator: checkNameRepeat, trigger: 'blur' }
        ],
        code: [
          {
            required: true,
            message: '部门编码不能为空',
            trigger: ['blur', 'change']
          },
          {
            min: 1,
            max: 50,
            message: '部门编码要求1-50个字符',
            trigger: ['blur', 'change']
          },
          { validator: checkCodeRepeat, trigger: 'blur' }
        ],
        manager: [
          {
            required: true,
            message: '部门负责人不能为空',
            trigger: ['blur', 'change']
          }
        ],
        introduce: [
          {
            required: true,
            message: '部门介绍不能为空',
            trigger: ['blur', 'change']
          },
          {
            min: 1,
            max: 300,
            message: '部门介绍要求1-300个字符',
            trigger: ['blur', 'change']
          }
        ]
      },
      //   部门负责人选项列表
      options: []
    }
  },
  methods: {
    // 关闭弹层
    handleClose() {
      // 下面两行代码都可以关闭弹层
      //  1.this.$emit('closeDialogFn')
      //  2.this.$emit('update:dialogVisible', false)
      //  但是想要使用第二种办法是由先决条件的；因为我们是从父组件传过来的，是控制弹层的显隐的；我们点击取消就要给这个传过来的值赋个false，但是不能直接修改prop接收的值，那就要使用子传父值得方法了；这就有了以上两个方法得出现。第二种方法需要在父组件传给子组件值的时候添加个async的修饰符，然后按照下面 this.$emit('update:dialogVisible', "要传的值")的固定格式书写就可以子组件向父组件传值了
      this.$emit('update:dialogVisible', false)
      this.$refs.deptForm.resetFields()
    },
    // 打开弹层自动触发的方法：调用获取部门列表负责人，并获取
    openDialog() {
      this.getDepartUser()
    },
    // 获取部门负责人列表
    async getDepartUser() {
      const list = await getDepartUserInfo()
      this.options = list.data
      //   console.log(this.options)
    },
    // 新增部门和编辑部门共用
    addDepartList() {
      // 点击了{确认键}，首先要对表单进行验证，不能有空的,如果为空不让通过
      // 然后将新增的数据添加到数据库
      // 最后关闭弹出框，并且清空表单数据

      this.$refs.deptForm.validate(async (valid) => {
        // 先对表单进行验证，只有验证通过了我们才能让其发起接口请求
        if (!valid) {
          // 校验不通过
          return
        } else {
          // 校验通过
          // 再来个if判断，因为添加部门和编辑部门用的是同一个方法
          if (this.form.id) {
            // 如果form这个对象有id，那就证明是编辑部门
            await editDepartMentApi(this.form)
            this.$message.success('编辑部门成功！')
          } else {
            // 新增部门
            const data = {
              ...this.form,
              pid: this.pdata.id
            }
            await addDepartMentApi(data)
            this.$message.success('新增部门成功！')
          }

          // 关闭弹层
          this.handleClose()
          // 重新渲染组织架构
          this.$emit('getDepartList')
        }
      })
    },
    // 获取部门详情
    async getDepartMent(id) {
      const res = await getDepartMentApi(id)
      console.log(res)
      this.form = res.data
    }
  }
}
</script>

<style></style>
